package com.sheyu.mall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import com.sheyu.common.constant.AuthServerConstant;
import com.sheyu.common.exception.BizCodeEnume;
import com.sheyu.common.utils.R;
import com.sheyu.common.vo.MemberResponseVo;
import com.sheyu.mall.auth.feign.MemberFeignService;
import com.sheyu.mall.auth.feign.ThirdPartFeignService;
import com.sheyu.mall.auth.vo.UserLoginVo;
import com.sheyu.mall.auth.vo.UserRegistVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author sheyu
 * @date 2020/8/19 9:30 下午
 */

@Controller
public class LoginController {

    @Autowired
    private ThirdPartFeignService thirdPartFeignService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    MemberFeignService memberFeignService;
/**
    @GetMapping("login.html")
    public String loginPage(){
        return "login";
    }

    @GetMapping("reg.html")
    public String regPage(){
        return "reg";
    }

    */

    /**
     * 1、从redis中抽取特定key值，判断是否在60s以内，以内就报error
     * 2、产生随机验证码，发送验证码，并将值存入redis以防止60s内重新刷
     * @param phone
     * @return
     */
    @ResponseBody
    @GetMapping("/sms/sendCode")
    public R sendCode(@RequestParam("phone") String phone){
        //1、接口防刷
        String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if(StringUtils.isNotBlank(redisCode)){
            long startTime = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis()-startTime<60000){
                //60s内不能重新发送
                return R.error(BizCodeEnume.SMS_CODE_EXCEPTION.getCode(),BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());
            }
        }
        int code = (int) ((Math.random() * 9 + 1) * 100000);
        String codeNum = String.valueOf(code);
        String redisStorage = codeNum + "_" + System.currentTimeMillis();

        //存入redis，防止60s内重刷
        stringRedisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone,redisStorage,10, TimeUnit.MINUTES);
        System.out.println(codeNum);
        //thirdPartFeignService.sendCode(phone,codeNum);
        return R.ok();
    }

    /**
     *  //TODO 重定向携带数据，利用session原理，将数据放在session中，只要跳到下一个页面取出这个数据以后，session里面的数据就会删除
     *
     *  //TODO 分布式下的seesion问题。
     * @param vo
     * @param result
     * @param attributes
     * @return
     */
    @PostMapping("/register")
    public String regist(@Valid UserRegistVo vo, BindingResult result, RedirectAttributes attributes){
        if (result.hasErrors()){
            Map<String,String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField,FieldError::getDefaultMessage));
            attributes.addFlashAttribute("errors",errors);
            return "redirect:http://localhost:20000/reg.html";
        }else{
            String code = vo.getCode();
            String s = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX+vo.getPhone());
            if(StringUtils.isNotBlank(s)){
                if (code.equals(s.split("_")[0])){
                    stringRedisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX+vo.getPhone());
                    R r = memberFeignService.register(vo);
                    if (r.getCode()==0){
                        //验证通过，注册用户，调用远程服务进行注册
                        return "redirect:http://localhost:20000/login.html";
                    }else{
                        Map<String,String> errors = new HashMap<>();
                        errors.put("msg",r.getData("msg",new TypeReference<String>(){}));
                        attributes.addFlashAttribute("errors",errors);
                    }
                }else{
                    //验证码出错。回到注册页面
                    Map<String,String> errors = new HashMap<>();
                    errors.put("code","验证码错误");
                    attributes.addFlashAttribute("errors",errors);
                    return "redirect:http://localhost:20000/reg.html";
                }
            }else{
                Map<String,String> errors = new HashMap<>();
                errors.put("code","验证码错误");
                attributes.addFlashAttribute("errors",errors);
                return "redirect:http://localhost:20000/reg.html";
            }
        }
        return "redirect:http://localhost:20000/reg.html";
    }

    @PostMapping("/login")
    public String login(UserLoginVo vo,RedirectAttributes attributes,HttpSession session){
        R login = memberFeignService.login(vo);
        if (login.getCode() == 0){
            //远程登陆
            MemberResponseVo data = login.getData("data",new TypeReference<MemberResponseVo>(){});
            session.setAttribute(AuthServerConstant.LOGIN_USER,data);
            return "redirect:http://localhost:10008";
        }else{
            Map<String,String> errors = new HashMap<>();
            errors.put("msg",login.getData("msg",new TypeReference<String>(){}));
            attributes.addFlashAttribute("errors",errors);
            return "redirect:http://localhost:20000/login.html";
        }
    }

    @GetMapping(value = "/login.html")
    public String loginPage(HttpSession session){

        //session先取出来用户的信息，判断用户是否已经登陆过了
        Object attribute = session.getAttribute(AuthServerConstant.LOGIN_USER);
        //如果用户没有登陆就跳转到登陆页面
        if(attribute==null){
            return "login";
        }else{
            return "redirect:http://localhost:10008";
        }
    }
    @GetMapping("/logout.html")
    public String logout(HttpServletRequest request){
        request.getSession().removeAttribute(AuthServerConstant.LOGIN_USER);
        request.getSession().invalidate();
        return "redirect:http://localhost:10008";
    }
}
